package reports

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"time"

	"shqsoft.cn/pasnj/base"
)

//BulidConfig 构建报表配置
type BulidConfig struct {
	BulidItems []BulidItem
}

//BuildAll 构建所有的项目
func (b *BulidConfig) BuildAll() error {
	for _, item := range b.BulidItems {
		if err := b.buildItem(&item); err != nil {
			return err
		}
	}
	return nil
}

//Build 构建执行编号的项目
func (b *BulidConfig) Build(no string) error {
	for _, item := range b.BulidItems {
		if item.NO == no {
			if err := b.buildItem(&item); err != nil {
				return err
			}
		}
	}
	return nil
}
func (b *BulidConfig) buildItem(item *BulidItem) error {
	bPath, err := base.ExecPath()
	if err != nil {
		return err
	}
	path := bPath + "/reportConfig/" + item.NO + ".json"
	isex, _ := base.Exists(path)
	if isex && !item.IsCover {
		return nil
	}
	ds, cols, err := b.buildDataSource(item.TableName, item.ProcName, item.Params)
	if err != nil {
		return err
	}
	params, err := b.buildParams(item.Params)
	if err != nil {
		return err
	}
	config := Config{
		Type:         item.Type,
		Name:         item.Name,
		KeyColumn:    item.KeyColumn,
		UserIDColumn: item.UserIDColumn,
		OrderBy:      item.OrderBy,
		Columns:      cols,
		Params:       params,
		DataSource:   *ds,
	}
	jsonBytes, err := json.Marshal(&config)
	if err != nil {
		return err
	}
	if err := ioutil.WriteFile(path, jsonBytes, 0644); err != nil {
		return err
	}
	return nil
}
func (b *BulidConfig) buildDataSource(tableName, procName string, pNames []string) (*DataSource, []Column, error) {
	var currdate time.Time
	row := base.DB.Raw("select sydt from t_conf_sydt").Row()
	if err := row.Scan(&currdate); err != nil {
		return nil, nil, err
	}
	var bCall, tName string
	if len(pNames) == 2 {
		year, month, _ := currdate.Date()
		mfDate := time.Date(year, month, 1, 0, 0, 0, 0, time.Local)
		tName = tableName + "_@sdate_@edate"
		bCall = procName + " @sdate,@edate"
		tableName = tableName + "_" + mfDate.Format("20060102") + "_" + currdate.Format("20060102")
		sql := fmt.Sprintf("exec %s ?,?", procName)
		base.DB.Exec(sql, mfDate, currdate)
	} else if len(pNames) == 1 {
		tName = tableName + "_@date"
		bCall = procName + " @date"
		tableName = tableName + "_" + currdate.Format("20060102")
		sql := fmt.Sprintf("exec %s ?", procName)
		base.DB.Exec(sql, currdate)
	} else {
		return nil, nil, fmt.Errorf("不支持的参数数量%d", len(pNames))
	}
	ds := &DataSource{
		Type: "table",
		Name: tName,
		BeforeCall: &CallBack{
			Type: "proc",
			Name: bCall,
		},
		AfterCall: nil,
	}
	sql := fmt.Sprintf(`select a.COLUMN_NAME,a.DATA_TYPE 
						from information_schema.COLUMNS as a  left join sys.extended_properties as b 
						on a.TABLE_NAME=OBJECT_NAME(b.major_id) and a.ORDINAL_POSITION=b.minor_id where a.TABLE_NAME='%s'`, tableName)
	rows, err := base.DB.Raw(sql).Rows()
	if err != nil {
		return nil, nil, err
	}
	defer rows.Close()
	cols := make([]Column, 0, 20)
	for rows.Next() {
		var name, dType string
		err := rows.Scan(&name, &dType)
		if err != nil {
			return nil, nil, err
		}
		dataType := "string"
		format := ""
		if dType == "int" || dType == "smallint" || dType == "bigint" {
			dataType = "int"
		} else if dType == "date" || dType == "datetime" {
			dataType = "date"
			format = "2006-01-02"
		} else if dType == "float" || dType == "money" || dType == "decimal" || dType == "numeric" || dType == "real" {
			dataType = "float"
			format = ".2f"
		}
		col := Column{
			Title:    name,
			Name:     name,
			Width:    100,
			DataType: dataType,
			Format:   format,
			Sorter:   true,
			Dispaly:  true,
			Filter:   true,
		}
		cols = append(cols, col)
	}
	return ds, cols, nil
}
func (b *BulidConfig) buildParams(pNames []string) ([]Parameter, error) {
	params := make([]Parameter, len(pNames), len(pNames))
	for i, name := range pNames {
		if name == "sdate" {
			params[i] = Parameter{
				Name:     "sdate",
				Caption:  "开始日期",
				DataType: "date",
				InitVal:  "#MONTHFIRSTDAY",
			}
		} else if name == "edate" {
			params[i] = Parameter{
				Name:     "edate",
				Caption:  "截至日期",
				DataType: "date",
				InitVal:  "#SYSDATE",
			}
		} else if name == "date" {
			params[i] = Parameter{
				Name:     "date",
				Caption:  "日期",
				DataType: "date",
				InitVal:  "#SYSDATE",
			}
		} else {
			return nil, fmt.Errorf("不支持的参数名称%s", name)
		}
	}
	return params, nil
}

//BulidItem 构建报表配置项
type BulidItem struct {
	NO           string   `json:"no"`
	Type         string   `json:"type"`
	Name         string   `json:"name"`
	KeyColumn    string   `json:"keyColumn"`
	UserIDColumn string   `json:"userIDColumn"`
	OrderBy      string   `json:"orderBy"`
	IsCover      bool     `json:"isCover"`
	Params       []string `json:"params"`
	TableName    string   `json:"tableName"`
	ProcName     string   `json:"procName"`
}

//NewBulidConfig 创建报表构建器
func NewBulidConfig() (*BulidConfig, error) {
	items, err := loadBulidConfig()
	if err != nil {
		return nil, err
	}
	return &BulidConfig{
		BulidItems: items,
	}, nil
}
func loadBulidConfig() (items []BulidItem, err error) {
	path, err := base.ExecPath()
	if err != nil {
		return
	}
	path = path + "/reportConfig/build.json"
	jsonBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}
	err = json.Unmarshal(jsonBytes, &items)
	return
}
